/*
 * Created on 2006-3-15
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package auditoryUIbk;
import java.io.*;

/**
  * An extension of a Reader to read and unread a stream a token at a time.
  * Someday will be able to ignore comments.
  *
  * WARNING: For some reason, nesting TokenReaders does not work.  I
  * don't know if it's a bug in the TokenReader or in the LineNumberReader.
  */
public class TokenReader extends Reader {
  protected String token;
  protected boolean isPushedBack = false;
  protected Reader delegate;
  
  public TokenReader(Reader reader)
  {
    super();
    delegate = reader;
  }

  public int read() throws IOException
  {
    int result;
    
    if (isPushedBack) {
      char c = token.charAt(0);
      token = token.substring(1);
      if (token.length() == 0) {
	isPushedBack = false;
      }
      result = Character.getNumericValue(c);
    }
    else {
      result = super.read();
    }

    return result;
  }
  
  public int read(char cbuf[],
		  int off,
		  int len) throws IOException
  {
    int result = 0;
    
    if (isPushedBack) {
      int length;
      if (token.length() <= len) {
	isPushedBack = false;
	length = token.length();
      }
      else {
	length = len;
      }
      token.getChars(0, length, cbuf, off);
      len -= length;
      off += length;
      if (isPushedBack) {
	// remove front of token
	token = token.substring(length);
      }
      result = length;
    }
    int actualBytesRead = delegate.read(cbuf, off, len);
    if (actualBytesRead != -1) {
      result += actualBytesRead;
    }
    else {
      result = -1;
    }

    return result;
  }

  public String readLine() throws IOException
  {
    StringBuffer result = new StringBuffer();
    
    if (isPushedBack) {
      result.append(token);
      isPushedBack = false;
    }
    int c;
    while (((c = read()) != '\n') && (c != -1)) {
      result.append((char) c);
    }
    return result.toString();
  }
  
  public long skip(long n) throws IOException
  {
    long skipped = 0;
    
    if (isPushedBack) {
      int tokenLength = token.length();
      skipped = (n < tokenLength) ? n : tokenLength;
      n -= skipped;
      token = token.substring((int) skipped);
      if (token.length() == 0) {
	isPushedBack = false;
      }
    }
    skipped += super.skip(n);

    return skipped;
  }

  /** maybe someday it could, but for now it doesn't */
  public boolean markSupported()
  {
    return false;
  }

  public void mark(int readAheadLimit) throws IOException
  {
    throw new IOException("mark/reset not supported");
  }
  
  public void reset() throws IOException
  {
    throw new IOException("mark/reset not supported");
  }
  
  public String readToken() throws IOException
  { 
    StringBuffer buf = new StringBuffer();

    final String whitespace = " \t\n\r";
    // first, get rid of whitespace
    int c;
    //System.err.print("white:'");
    do {
      c = read();
      if (c == -1) {
	throw new EOFException();
      }
      //System.err.print((char) c);
    } while (whitespace.indexOf(c) != -1);
    //System.err.println("'");

    buf.append((char) c);
    // now read the actual token
    boolean done = false;
    //System.err.print("token:'");
    while (!done) {
      c = read();
      if (c == -1) {
	throw new EOFException();
      }
      //System.err.print((char) c);
      if (whitespace.indexOf(c) != -1) {
	done = true;
      }
      else {
	buf.append((char) c);
      }
    }
    //System.err.println("readToken: '" + buf + "'");

    return buf.toString();
  }

  public int readInt() throws IOException, NumberFormatException
  {
    return Integer.parseInt(readToken());
  }

  public long readLong() throws IOException, NumberFormatException
  {
    return Long.parseLong(readToken());
  }

  public boolean readBoolean() throws IOException
  {
    return Boolean.valueOf(readToken()).booleanValue();
  }

  /** can only unread 1 string at a time */
  public void unreadString(String s)
  {
    token = s;
    isPushedBack = true;
  }

  public void close() throws IOException
  {
    delegate.close();
  }
  
  public static void main(String[] args)
  {
    TokenReader reader = new TokenReader(new InputStreamReader(System.in));
    boolean done = false;
    do {
      try {
	String token = reader.readToken();
	System.out.println("'" + token + "'");
	token = reader.readLine();
	System.out.println("'" + token + "'");
      }
      catch (EOFException e) {
	done = true;
      }
      catch (IOException e) {
	System.err.println(e);
	done = true;
      }
    } while (!done);
  }
}